#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <vector>
#include <functional>
using namespace std;

namespace my_pthread
{
    template <class T>
    using fun = function<void(T *)>;

    template <class T>
    class mypthread
    {
    public:
        static void *pthread_function(void *formal)
        {
            mypthread<T> *tmp = static_cast<mypthread<T> *>(formal);
            tmp->work();
            return nullptr;
        }

        void work()
        {
            _fun(_data);
        }

        mypthread(string name, fun<T> function, T *data) : _name(name), _run(false), _fun(function), _data(data)
        {
        }

        ~mypthread()
        {
        }

        bool start()
        {
            int i = pthread_create(&_id, nullptr, pthread_function, this);
            if (i == 0)
            {
                _run = true;
            }
            else
            {
                return false;
            }
            return true;
        }

        void join()
        {
            if (_run)
            {
                pthread_join(_id, nullptr);
            }
        }

        void Detach()
        {
            if (_run)
            {
                pthread_detach(_id);
            }
        }

        void stop()
        {
            _run = false;
        }

    private:
        string _name;
        pthread_t _id;
        bool _run;
        fun<T> _fun;
        T *_data;
    };

    // 封装锁
    class mypthread_mutex_t
    {
    public:
        mypthread_mutex_t(pthread_mutex_t &mutex) : _mutex(mutex)
        {
            pthread_mutex_lock(&_mutex);
        }

        ~mypthread_mutex_t()
        {
            pthread_mutex_unlock(&_mutex);
        }

    private:
        pthread_mutex_t &_mutex;
    };
}

class ThreadData
{
public:
    ThreadData(string name, int& tick, pthread_mutex_t& mutex) : _name(name),  _total(tick), _mutex(mutex)
    {
    }

    ~ThreadData()
    {
    }
    
    string _name;
    int _tick;
    pthread_mutex_t &_mutex;
    int& _total;
};